
#include<Lcode/l_main.h>

int bw_is_data_reg( L_Operand * operand)
{
	return (!L_is_pointer(operand))&&(L_is_variable(operand));
}

int bw_is_addr_reg(L_Operand *operand)
{
	return L_is_pointer(operand)&&L_is_variable(operand);
}

int bw_is_imm_or_label( L_Operand *operand)
{
	if( operand == NULL)
		return 0;
	
	return (operand->type == L_OPERAND_IMMED || operand->type == L_OPERAND_LABEL);
}

int bw_is_label(L_Operand * opd)
{
	if(opd == NULL)
		return 0;
	return (opd->type == L_OPERAND_LABEL);
}

int bw_is_imm(L_Operand * opd)
{
	if(opd == NULL)
		return 0;
	return (opd->type == L_OPERAND_IMMED);
}

int bw_is_cb(L_Operand * opd)
{
	if(opd == NULL)
		return 0;
	return (opd->type == L_OPERAND_CB);
}


int bw_is_gen_data_reg(L_Operand * operand)
{
	if( !operand)
		return  0;

	if( bw_is_data_reg(operand))
	{
		if(operand->type == L_OPERAND_REGISTER)
			return 1; 
	}
	return  0;
}



int bw_is_mac_data_reg(L_Operand * operand)
{
	if(!operand)
		return 0;		
	if( operand->type == L_OPERAND_MACRO)
	{
		switch( operand->value.mac )
		{
			case L_MAC_P0:
			case L_MAC_P1:
			case L_MAC_P2:
			case L_MAC_P3:
			case L_MAC_P10:
				return 1;
		}
	}
	return 0;
}

int bw_is_mac_addr_reg(L_Operand * operand)
{
	if( !operand)
		return 0;
	if( operand->type == L_OPERAND_MACRO)
	{
		switch (operand->value.mac )
		{
			case L_MAC_P4 :
			case L_MAC_P5 :
			case L_MAC_P6 :
			case L_MAC_P7 :

			case L_MAC_IP :  /* pointer to incoming parameter space */
  			case L_MAC_OP :  /* pointer to outgoing parameter space */

			case L_MAC_LV :

  			case L_MAC_RS :  /* pointer to register swap space      */
  			case L_MAC_SP :
  			case L_MAC_FP :
				return 1;
			default:
				return 0;
		}
	}
	return 0;
}

int bw_is_gen_addr_reg(L_Operand * operand)
{
	if(!operand)
		return 0;
	if(L_is_reg(operand) &&  operand->ctype == L_CTYPE_POINTER)
	{
		return 1;	
	}
	return 0;
}


int is_supported_by_AGU(L_Oper * oper)
{
	switch (oper->opc)
	{
		case Lop_ADD:
		case Lop_ADD_U:
			return 1;
	}
	
	if( (oper->opc == Lop_SUB || oper->opc == Lop_SUB_U)
		  &&(oper->src[1]->type == L_OPERAND_IMMED))
		return 1;
	if( (oper->opc == Lop_MOV  && oper->src[0]->type == L_OPERAND_IMMED))
		return 1;

	return 0;
}

int bw_is_simd_start(L_Oper *oper)
{
	if(oper->opc != Lop_DEFINE)
		return 0;
	L_Attr *attr = L_find_attr(oper->attr, "simd_start");
	if(attr == NULL)
		return 0;
	return 1;
}


int bw_is_simd_end(L_Oper *oper)
{
	if(oper->opc != Lop_DEFINE)
		return 0;
	L_Attr *attr = L_find_attr(oper->attr, "simd_end");
	if(attr == NULL)
		return 0;
	return 1;
}
/*
 * the load can only process the Lop_LD_F, Lop_LD_I, Lop_LD_UI
 */
int bw_is_simd_load(L_Oper * oper)
{
	if(oper->opc != Lop_DEFINE)
		return 0;
	L_Attr * attr = L_find_attr(oper->attr, "interval");
	if(!attr)
	{
		return 0;
	}
	L_Oper *mem_oper = oper->next_op;
#ifdef DEBUG_CHECK
	if(mem_oper == NULL)
		L_punt("bw_is_simd_load: error, the oper->next_op is expected");
#endif
	if(
		mem_oper->opc ==  Lop_LD_F||
		mem_oper->opc ==  Lop_LD_I||
		mem_oper->opc ==  Lop_LD_UI
	)
		return 1;
	else
		return 0;
}


int bw_is_simd_store(L_Oper *oper)
{
	L_Attr *attr = L_find_attr(oper->attr, "interval");
	if(!attr)
	{
		return 0;
	}
	L_Oper *mem_oper = oper->next_op;
	if(
		mem_oper->opc == Lop_ST_F ||
		mem_oper->opc == Lop_ST_I
		)
		return 1;
	else
		return 0;
}


int bw_is_ignored_oper(L_Oper *oper)
{
	//process the simd operation
	if(bw_is_simd_start(oper) || bw_is_simd_end(oper))
		return 0;
	if(oper->opc == Lop_DEFINE ||
		oper->opc == Lop_PROLOGUE ||
		oper->opc == Lop_EPILOGUE )
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int bw_is_unroll_cb(L_Cb *cb)
{
	L_Attr * attr = L_find_attr(cb->attr, "bw_unroll_AMP");
	if(attr == NULL)
		return 0;
	else
		return 1;
}
int bw_is_loop_header(L_Cb *cb)
{
	L_Attr *attr = L_find_attr(cb->attr, "bw_roll_header");
	if(attr == NULL)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int bw_is_loop_remainder(L_Cb* cb)
{
	L_Attr *attr = L_find_attr(cb->attr, "bw_unroll_remainder");
	if(attr == NULL)
	{
		return 0;
	}
	else
		return 1;
}

